#include "Whiteboard.h"
#include <QtGui>

Whiteboard::Whiteboard(QWidget* pParent):
    QWidget(pParent), _penColor(Qt::black),
    _penWidth(2), _modified(false),
    _drawing(false)
{
    setAttribute(Qt::WA_StaticContents);
    _image.fill(qRgb(255, 255, 255));
}

//Whiteboard::~Whiteboard(void)
//{
//}

bool Whiteboard::loadImage(const QString& fileName)
{
    QImage loadedImage;
    if (!loadedImage.load(fileName))
        return false;

    QSize newSize = loadedImage.size().expandedTo(size());
    resizeImage(&loadedImage, newSize);
    _image = loadedImage;

    _modified = false;
    update();

    return true;
}

bool Whiteboard::saveImage(const QString& fileName, const char* fileFormat)
{
    QImage visibleImage = _image;
    resizeImage(&visibleImage, size());

    if (visibleImage.save(fileName, fileFormat)) {
        _modified = false;
        return true;
    } else
        return false;
}

void Whiteboard::setPenColor(const QColor& newColor)
{
    _penColor = newColor;
}

QColor Whiteboard::getPenColor(void) const
{
    return _penColor;
}

void Whiteboard::setPenWidth(int newWidth)
{
    _penWidth = newWidth;
}

int Whiteboard::getPenWidth(void) const
{
    return _penWidth;
}

bool Whiteboard::isModified(void) const
{
    return _modified;
}

void Whiteboard::drawLineTo(const QPoint& endPoint)
{
    QPainter painter(&_image);
    painter.setPen(QPen(_penColor, _penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));

    painter.drawLine(_lastPoint, endPoint);
    _modified = true;

    int rad = (_penWidth / 2) + 2;
    update(QRect(_lastPoint, endPoint).normalized().adjusted(-rad, -rad, +rad, +rad));

    _lastPoint = endPoint;
}

void Whiteboard::resizeImage(QImage* pImage, const QSize& newSize)
{
    if (pImage->size() == newSize)
        return;

    QImage newImage(newSize, QImage::Format_RGB32);
    newImage.fill(qRgb(255, 255, 255));

    QPainter painter(&newImage);
    painter.drawImage(QPoint(0, 0), *pImage);
    *pImage = newImage;
}

void Whiteboard::mousePressEvent(QMouseEvent* pEvent)
{
    if (pEvent->button() == Qt::LeftButton) {
        _lastPoint = pEvent->pos();
        _drawing = true;
    }
}

void Whiteboard::mouseReleaseEvent(QMouseEvent* pEvent)
{
    if (pEvent->button() == Qt::LeftButton && _drawing) {
        drawLineTo(pEvent->pos());
        _drawing = false;
    }
}

void Whiteboard::mouseMoveEvent(QMouseEvent* pEvent)
{
    if (_drawing)
        drawLineTo(pEvent->pos());
}

void Whiteboard::paintEvent(QPaintEvent* pEvent)
{
    QPainter painter(this);
    QRect rect = pEvent->rect();
    painter.drawImage(rect, _image, rect);
}

void Whiteboard::resizeEvent(QResizeEvent* pEvent)
{
    if (width() > _image.width() || height() > _image.height()) {
        int newWidth = qMax(width() + 128, _image.width());
        int newHeight = qMax(height() + 128, _image.height());
        resizeImage(&_image, QSize(newWidth, newHeight));
        update();
    }

    QWidget::resizeEvent(pEvent);
}

void Whiteboard::clearImage(void)
{
    _image.fill(qRgb(255, 255, 255));
    _modified = true;
    update();
}

void Whiteboard::contextMenu(const QPoint& pos)
{
	QMenu* menu = new QMenu;

	menu->addAction(tr("&Load Image"), this, SLOT(menuLoadImage()));
	menu->addAction(tr("&Save Image"), this, SLOT(menuSaveImage()));
	menu->addSeparator();
	menu->addAction(tr("Pen &Color"), this, SLOT(menuPenColor()));
	menu->addAction(tr("Pen &Width"), this, SLOT(menuPenWidth()));

	menu->exec(mapToGlobal(pos));
}

void Whiteboard::menuLoadImage(void)
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("Open Image"),
		QDir::currentPath(),
		tr("Images (*.bmp *.ico *.jpeg *.jpg *.png *.ppm *.tif *.tiff *.xbm *.xpm)"
		"*.bmp;;*.ico;;*.jpeg;;*.jpg;;*.png;;*.ppm;;*.tif;;*.tiff;;*.xbm;;*.xpm;;All files (*.*)"));

	if (!fileName.isEmpty())
		loadImage(fileName);
}

void Whiteboard::menuSaveImage(void)
{
	QString fileName = QFileDialog::getSaveFileName(this, tr("Save Image"),
		QDir::currentPath(),
		tr("Images (*.bmp *.ico *.jpeg *.jpg *.png *.ppm *.tif *.tiff *.xbm *.xpm)"
		";;*.bmp;;*.ico;;*.jpeg;;*.jpg;;*.png;;*.ppm;;*.tif;;*.tiff;;*.xbm;;*.xpm;;All files (*.*)"));

	if (!fileName.isEmpty()) {
		char format[20];

		int i = 0;
		int j = fileName.lastIndexOf('.') + 1;
		for (; j < fileName.size(); ++i, ++j)
			format[i] = fileName[j].toAscii();

		format[i] = 0;

		saveImage(fileName, format);
	}
}

void Whiteboard::menuPenColor(void)
{
	QColor newColor = QColorDialog::getColor(_penColor);
	if (newColor.isValid())
		_penColor = newColor;
}

void Whiteboard::menuPenWidth(void)
{
	bool valid;
	int newWidth = QInputDialog::getInteger(this, tr("Whiteboard"),
	                                        tr("Select line width:"),
											_penWidth,
	                                        1, 50, 1, &valid);

	if (valid)
		_penWidth = newWidth;
}
